Coverage Report

Created: 2024-12-26 12:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\tools.proto\tools.proto\runtime\src\message\interface.rs
Line
Count
Source
1
// Copyright (c) 2024, BlockProject 3D
2
//
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification,
6
// are permitted provided that the following conditions are met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above copyright notice,
11
//       this list of conditions and the following disclaimer in the documentation
12
//       and/or other materials provided with the distribution.
13
//     * Neither the name of BlockProject 3D nor the names of its contributors
14
//       may be used to endorse or promote products derived from this software
15
//       without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
use bp3d_util::simple_error;
30
31
simple_error! {
32
    pub Error {
33
        InvalidUtf8 => "invalid UTF-8 string",
34
        Truncated => "truncated input",
35
        InvalidUnionDiscriminant(usize) => "invalid union discriminant ({})",
36
        (impl From) Io(std::io::Error) => "io error: {}"
37
    }
38
}
39
40
pub type Result<T> = std::result::Result<T, Error>;
41
42
#[derive(Default, Copy, Clone, Debug)]
43
pub struct FieldOffset {
44
    pub start: usize,
45
    pub end: usize,
46
}
47
48
impl FieldOffset {
49
6
    pub fn size(&self) -> usize {
50
6
        self.end - self.start
51
6
    }
52
}
53
54
pub struct Message<T> {
55
    data: T,
56
    size: usize,
57
}
58
59
impl<T> Message<T> {
60
530
    pub fn new(size: usize, data: T) -> Self {
61
530
        Self { data, size }
62
530
    }
63
64
514
    pub fn into_inner(self) -> T {
65
514
        self.data
66
514
    }
67
68
518
    pub fn size(&self) -> usize {
69
518
        self.size
70
518
    }
71
72
68
    pub fn map<T1, F: FnOnce(T) -> T1>(self, f: F) -> Message<T1> {
73
68
        Message::new(self.size(), f(self.into_inner()))
74
68
    }
75
}
76
77
pub trait FromBytes<'a> {
78
    type Output: Sized;
79
80
    fn from_bytes(slice: &'a [u8]) -> Result<Message<Self::Output>>;
81
    //fn copy_to_slice(&self, out_slice: &mut [u8]);
82
}
83
84
pub trait FromBytesWithOffsets<'a>: FromBytes<'a> {
85
    type Offsets: Sized;
86
87
    fn from_bytes_with_offsets(slice: &'a [u8]) -> Result<Message<(Self::Output, Self::Offsets)>>;
88
}
89
90
pub trait WriteTo {
91
    type Input<'a>: Sized;
92
93
    fn write_to<W: std::io::Write>(input: &Self::Input<'_>, out: W) -> Result<()>;
94
}
95
96
pub trait ShapeAndWrite {
97
    fn shape_and_write<W: std::io::Write>(self, out: W) -> Result<()>;
98
}
99
100
#[cfg(feature = "tokio")]
101
pub trait ShapeAndWriteAsync {
102
    fn shape_and_write_async<W: tokio::io::AsyncWriteExt + Unpin>(self, out: W) -> impl std::future::Future<Output = Result<()>>;
103
}
104
105
#[cfg(feature = "tokio")]
106
pub trait WriteToAsync: WriteTo {
107
    fn write_to_async<W: tokio::io::AsyncWriteExt + Unpin>(
108
        input: &Self::Input<'_>,
109
        out: W,
110
    ) -> impl std::future::Future<Output = Result<()>>;
111
}
112
113
pub trait WriteSelf {
114
    fn write_self<W: std::io::Write>(&self, out: W) -> Result<()>;
115
    fn size(&self) -> Result<usize>;
116
}
117
118
#[cfg(feature = "tokio")]
119
pub trait WriteSelfAsync {
120
    fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(
121
        &self,
122
        out: W,
123
    ) -> impl std::future::Future<Output = Result<()>>;
124
}
125
126
pub trait FromBytesWithHeader<'a, H> {
127
    type Output: Sized;
128
129
    fn from_bytes_with_header(slice: &'a [u8], header: &H) -> Result<Message<Self::Output>>;
130
}
131
132
pub trait WriteToWithHeader<H> {
133
    type Input<'a>: Sized;
134
135
    fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, header: &H, out: W) -> Result<()>;
136
}
137
138
pub trait ShapeHeader<H> {
139
    fn shape_header(&self, header: &mut H) -> Result<()>;
140
}
141
142
impl<H, T: WriteSelf> ShapeHeader<H> for T {
143
0
    fn shape_header(&self, _: &mut H) -> Result<()> {
144
0
        Ok(())
145
0
    }
146
}
147
148
#[cfg(feature = "tokio")]
149
pub trait WriteToWithHeaderAsync<H>: WriteToWithHeader<H> {
150
    fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(
151
        input: &Self::Input<'_>,
152
        header: &H,
153
        out: W,
154
    ) -> impl std::future::Future<Output = Result<()>>;
155
}
156
157
impl<'a, T: WriteTo<Input<'a> = T>> WriteSelf for T {
158
8
    fn write_self<W: std::io::Write>(&self, out: W) -> Result<()> {
159
8
        T::write_to(self, out)
160
8
    }
161
162
4
    fn size(&self) -> Result<usize> {
163
4
        crate::message::util::size_of(self)
164
4
    }
165
}
166
167
#[cfg(feature = "tokio")]
168
impl<T> WriteSelfAsync for T
169
where
170
    for<'a> T: WriteToAsync<Input<'a> = T>,
171
{
172
7
    async fn write_self_async<W: tokio::io::AsyncWriteExt + Unpin>(&self, out: W) -> Result<()> {
173
7
        T::write_to_async(self, out).await
174
7
    }
175
}
176
177
impl<H, T: WriteSelf> WriteToWithHeader<H> for T {
178
    type Input<'b> = T;
179
180
2
    fn write_to_with_header<W: std::io::Write>(input: &Self::Input<'_>, _: &H, out: W) -> Result<()> {
181
2
        input.write_self(out)
182
2
    }
183
}
184
185
#[cfg(feature = "tokio")]
186
impl<H, T: WriteSelf + WriteSelfAsync> WriteToWithHeaderAsync<H> for T {
187
2
    fn write_to_with_header_async<W: tokio::io::AsyncWriteExt + Unpin>(
188
2
        input: &Self::Input<'_>,
189
2
        _: &H,
190
2
        out: W,
191
2
    ) -> impl std::future::Future<Output = Result<()>> {
192
2
        input.write_self_async(out)
193
2
    }
194
}
195
196
impl<'a, H, T: FromBytes<'a>> FromBytesWithHeader<'a, H> for T {
197
    type Output = T::Output;
198
199
0
    fn from_bytes_with_header(slice: &'a [u8], _: &H) -> Result<Message<Self::Output>> {
200
0
        T::from_bytes(slice)
201
0
    }
202
}